Vue3基础知识

练习demo可以使用sfc:  https://sfc.vuejs.org/

01 vite脚手架创建vue3.0项目

(1) 创建vue3项目

  1. npm install -g create-vite-app

  2. create-vite-app projectName

  3. cd projectName

  4. npm install

  5. npm run dev vit的特点就是: 快

  6. sass支持

  1. 代码: 要写scss而不是sass
<style lang="scss" scoped>
div {
    p {
        color: red;
    }
}
</style>

(2) 创建vue3+ts项目

  1. 执行命令 npm init vite@latest

    npm init @vitejs/app vue3_ts_vite
    
  2. 根据提示输入项目名称,选择vue+ts

  3. 安装依赖

  4. 运行项目

02 setup入口函数

  1. 使用setup函数和更好的管理我们的代码
  2. vue2.x的data、methods、computed、watch通通写进了setup函数里面
  3. 一个简单例子
<template>
	<div>{{activeIndex}}</div>  
</template>

<script>
import { getUsers } from "../api/repo";
import UserRepoList from "./userRepoList.vue";
import {onMounted, ref} from 'vue';
export default {
  components: {
    UserRepoList,
  },

  setup() {
    // 把data的东西移到这里
    const activeIndex = ref('');
    const userId = ref('');
    const userList = ref([]);

    // 把methods移到这里
    const getUserList=()=>{
       userList.value = getUsers();
    }
    const changeUser = (id,index)=>{ 
      activeIndex.value = index;
      userId.value = id;
    }
    // onMounted是介于beforeCreated和created的生命周期, 没有this
    onMounted(getUserList);

    // 相当于2.x data(){}里的return,其他地方
     return {
      activeIndex,
      userId,
      userList,
      changeUser
    };
  }   
};
</script>

03 ref 创建响应式数据(2.x的data)

<template>
  <div style="margin: 30px">
    <p>
    {{count}} 
  </p>
  <ol>
      <li v-for="(item,index) in list" :key="index">{{item}}</li> 
   </ol>
  </div>
</template>
<script> 

import {ref} from 'vue';
export default { 
  setup(props) {
    const count = ref(0); 
    const list = ref(['a','b','c']);
    return {
      count,
      list
    };
  },
};
</script>

reactive用法与ref的用法相似,也是将数据变成响应式数据,当数据发生变化时UI也会自动更新。不同的是ref用于基本数据类型,而reactive是用于复杂数据类型,比如对象和数组 例如:定义一个对象类型的变量user

<template>
  <div>
    <p>{{ user }}</p>
    <button @click="increase">click me! one year later</button>
  </div>
</template>
 
<script>
import { reactive } from "vue";
export default {
  name: "reactive",
  setup() {
    const user = reactive({ name: "Alice", age: 12 });
    function increase() {
      ++user.age
    }
    return { user, increase };
  },
};
</script>

04 定义方法和修改响应式数据

  1. 响应式数据通过count.value = xxx 进行重新赋值
  2. 方法定义在setup函数里, 并放在return对象里
<template>
  <div> 
    <h3>{{msg}}</h3>
    <button @click="changeMsg">修改msg</button>

    <h3>{{count}}</h3>
    <button @click="changeCount">修改count</button>


    <h3>列表 <button @click="changeList">修改list</button></h3>
    <ul class="flex">
      <li class="ml-5" v-for="(item,index) in list" :key="index">{{item}}</li>
    </ul>
  </div>
</template>

<script> 
import { defineComponent, ref } from 'vue';
export default defineComponent({
  name: "App", 

  setup(props) {
    let msg = ref('hello');
    // 定义修改msg的方法
    const changeMsg = ()=> {
      msg.value = 'hello vue3';
    }

    // 定义修改count的方法
    let count = ref(0);
    const changeCount =()=> {
      count.value++;
    }

    // 定义修改list的方法
    let list = ref(['a','b','c','d']);
    const changeList = ()=> { 
      list.value = [
        ...list.value,
        '新成员',
        '新成员',
      ]
    }

    return {
      msg,
      changeMsg,
      count,
      changeCount,
      list,
      changeList
    };
  },
});
</script>

05 toRefs 把props变成响应式数据

<template>
  <div style="margin: 30px">
    {{ count }}
  </div>
</template>
<script>
import { toRefs } from "vue";
export default {
  props: {
    count: {
      type: Number,
      default: 10,
    }
  },
  setup(props) {
    const { count } = toRefs(props);
    return {
      count,
    };
  },
};
</script>

06 onMounted

新的生命周期函数, 介于beforeCreate和created之间一个声明周期函数, 有两种调用方法

<template>
  <div>
    <ol>
      <li v-for="(item,index) in list" :key="index">{{index+1}}. {{item.name}}</li>
    </ol>

  </div>
</template>

<script>
import { defineComponent, onMounted, ref } from "vue";
import axios from 'axios';
export default defineComponent({
  name: "App", 
   
  setup() {
    // 定义一个响应式的变量list
    const list = ref([]);
    // 获取数据
    const getList = ()=> {
      axios.get('http://huruqing.cn:3000/api/film/getList').then(res=> {
        // 修改list,页面重新渲染
        list.value = res.data.films;
      })
    }
    // 在声明周期函数里自动调用getList去获取数据
    onMounted(getList);

    return {
      list,
      getList
    };
  },
});
</script>

07 watch函数

<template>
  <div> 
    <h3>{{count}}</h3>
    <button @click="count=100">修改count</button>
  </div>
</template>

<script>
import { defineComponent, ref, watch} from "vue";  
export default defineComponent({
  name: "App",  
   
  setup() { 
    const count = ref(0);
    watch(count,(n,o)=> {
      console.log('新值',n);
      console.log('旧值',o);
    })

    return {
      count,
    };
  },
});
</script>

08 computed函数

(1)第一种情况: count2根据count计算得到

<template>
  <div style="margin: 30px">
    {{ count }}  
  </div>
  <div style="margin: 30px">
    {{ count2 }}  
  </div> 
</template>
<script>
import { computed, ref, watch } from "vue";
export default {
  setup(props) {
    const count = ref(1);
    const count2 = computed(() => count.value + 10); 
    return {
      count,
      count2, 
    };
  },
};
</script>

(2) 第二种情况: count2根据count得到, 修改count2的同时也修改count的值

<template>
  <div style="margin: 30px">
    {{ count }}
  </div>
  <div style="margin: 30px">
    {{ count2 }}
  </div>
</template>
<script>
import { computed, ref, watch } from "vue";
export default {
  setup(props) {
    const count = ref(1);
    const count2 = computed({
      get: () => count.value + 1,
      set: (val) => {
        count.value = val - 1;
      },
    });

    setTimeout(()=> {
      count2.value = 10;
    },2000)
    return {
      count,
      count2,
    };
  },
};
</script>

09 父子组件通信

  1. 父传子, 通过属性
  2. 子传父, 通过emit
// 父组件
<template>
  <div>  
    <!-- 使用Hello组件需要提供msg,Hello组件提供了send事件给父组件 -->
    <Hello :msg="msg" @send="test"/>
  </div>
</template>

<script>
import {defineComponent, ref} from "vue"; 
import Hello from './Hello.vue' 
export default defineComponent({
  name: "App",  
   components: {
     Hello,
   },
  setup() {   
    const msg = ref('hello');

    const test =(data)=> {
      console.log(data);
    }
    return { 
      msg,
      test
    };
  },
});
</script>

// 子组件
<template>
  <div>
    <h3>{{ msg }}</h3>
    <!-- 通过emit发送数据给父组件 -->
    <button @click="emit('send',22222222222)">发送信息</button>
  </div>
</template>

<script>
import { defineComponent, toRefs } from "vue";
export default defineComponent({
  props: {
    msg: {
      type: String,
    },
  },

  /**
   * @param props父组件传过来的属性
   * @param context上下文对象
   */
  setup(props, context) {
    console.log("上下文对象", context);
    const { msg } = toRefs(props);
    // 把emit方法从context对象结构出来
    const { emit } = context;

    return {
      msg,
      emit
    };
  },
});
</script> 

10 script标签的setup属性

<template>
  <h1>{{ msg }}</h1>
</template>

<script setup>
const msg = 'Hello World!'
</script>

一些资源: Vue3+TypeScript 完整项目上手教程